package hygprs

import (
	"encoding/hex"
	"time"
)

/*
视频指令
*/
type CommonVideoCommand struct {
	base1246
}

func (e *CommonVideoCommand) GetActionType() byte {
	return e.data[27]
}

func (e *CommonVideoCommand) SetActionType(v byte) {
	e.data[27] = v
}

func (e *CommonVideoCommand) GetStatusActionCode() byte {
	return e.data[28]
}

func (e *CommonVideoCommand) SetStatusActionCode(v byte) {
	e.data[28] = v
}

func (e *CommonVideoCommand) GetTransMode() byte {
	return e.data[31]
}

func (e *CommonVideoCommand) SetTransMode(v byte) {
	e.data[31] = v
}

func (e *CommonVideoCommand) SetTimeRange(start, end uint32) {
	copy(e.data[32:36], FromUint32(start))
	copy(e.data[36:40], FromUint32(end))
}

func (e *CommonVideoCommand) SetServerAddr(addr string) {
	copy(e.data[40:47], FromIPAddr(addr))
}

func (e *CommonVideoCommand) IsNewer() bool {
	return e.data[27] == 0x10
}

func (e *CommonVideoCommand) ToNewer() *NewerVideoCommand {
	return &NewerVideoCommand{*e}
}

func (e *CommonVideoCommand) ToOlder() *OlderVideoCommand {
	return &OlderVideoCommand{*e}
}

/*
新协议视频指令
*/
type NewerVideoCommand struct {
	CommonVideoCommand
}

func (*NewerVideoCommand) Template() []byte {
	data, _ := hex.DecodeString("a000360203afc2010000003402000014520403b978770660fe4c53100100010100000000000000000a26e87bff1d0001010000095fa1")
	return data
}

func (e *NewerVideoCommand) Load(data []byte) (msg string, ok bool) {
	if len(data) != 54 {
		return "长度错误", false
	}
	return e.CommonVideoCommand.Load(data)
}

func (e *NewerVideoCommand) GetVideoCode() uint16 {
	return ToUint16(e.data[29:31])
}

func (e *NewerVideoCommand) SetVideoCode(v uint16) {
	copy(e.data[29:31], FromUint16(v))
}

func (e *NewerVideoCommand) GetAudioCode() uint16 {
	return ToUint16(e.data[46:48])
}

func (e *NewerVideoCommand) SetAudioCode(v uint16) {
	copy(e.data[46:48], FromUint16(v))
}

func (e *NewerVideoCommand) SetPassageCode(video, audio uint16) {
	e.SetVideoCode(video)
	e.SetAudioCode(audio)
}

func (*NewerVideoCommand) Make(line, bus, op uint32, video, audio uint16, mode byte, addr string) []byte {
	cmd := new(NewerVideoCommand)
	cmd.Load(cmd.Template())
	cmd.SetLineID(line)
	cmd.SetBusID(bus)
	cmd.SetOperatorID(op)
	cmd.SetTimeStamp(uint32(time.Now().Unix()))
	cmd.SetActionType(0x10)
	cmd.SetStatusActionCode(0x01)
	cmd.SetPassageCode(video, audio)
	cmd.SetTransMode(mode)
	cmd.SetServerAddr(addr)
	return cmd.Done()
}

/*
旧协议视频指令
*/
type OlderVideoCommand struct {
	CommonVideoCommand
}

func (*OlderVideoCommand) Template() []byte {
	data, _ := hex.DecodeString("a000330203afc2010000003402000014520403b978770660fe4c53100100010100000000000000000a26e87bff1d0000095fa1")
	return data
}

func (e *OlderVideoCommand) Load(data []byte) (msg string, ok bool) {
	if len(data) != 51 {
		return "长度错误", false
	}
	return e.CommonVideoCommand.Load(data)
}

func (e *OlderVideoCommand) GetPassageCode() uint16 {
	return ToUint16(e.data[29:31])
}

func (e *OlderVideoCommand) SetPassageCode(v uint16) {
	copy(e.data[29:31], FromUint16(v))
}

func (*OlderVideoCommand) MakeVideo(line, bus, op uint32, video uint16, mode byte, addr string) []byte {
	cmd := new(OlderVideoCommand)
	cmd.Load(cmd.Template())
	cmd.SetLineID(line)
	cmd.SetBusID(bus)
	cmd.SetOperatorID(op)
	cmd.SetTimeStamp(uint32(time.Now().Unix()))
	cmd.SetActionType(0x01)
	cmd.SetStatusActionCode(0x01)
	cmd.SetPassageCode(video)
	cmd.SetTransMode(mode)
	cmd.SetServerAddr(addr)
	return cmd.Done()
}

func (*OlderVideoCommand) MakeAudio(line, bus uint32, audio uint16, mode byte, addr string) []byte {
	cmd := new(OlderVideoCommand)
	cmd.Load(cmd.Template())
	cmd.SetLineID(line)
	cmd.SetBusID(bus)
	cmd.SetTimeStamp(uint32(time.Now().Unix()))
	cmd.SetActionType(0x02)
	if audio != 0 {
		cmd.SetStatusActionCode(0x03)
	} else {
		cmd.SetStatusActionCode(0x04)
	}
	cmd.SetPassageCode(audio)
	cmd.SetTransMode(mode)
	cmd.SetServerAddr(addr)
	return cmd.Done()
}

/*
视频数据流
*/
type CommonVideoStream struct {
	base1246
}

func (e *CommonVideoStream) GetActionType() byte {
	return e.data[27]
}

func (e *CommonVideoStream) SetActionType(v byte) {
	e.data[27] = v
}

func (e *CommonVideoStream) GetStatusActionCode() byte {
	return e.data[28]
}

func (e *CommonVideoStream) SetStatusActionCode(v byte) {
	e.data[28] = v
}

func (e *CommonVideoStream) GetPassageStatus() uint16 {
	return ToUint16(e.data[29:31])
}

func (e *CommonVideoStream) SetPassageStatus(v uint16) {
	copy(e.data[29:31], FromUint16(v))
}

func (e *CommonVideoStream) GetTransMode() byte {
	return e.data[32]
}

func (e *CommonVideoStream) SetTransMode(v byte) {
	e.data[32] = v
}

func (e *CommonVideoStream) IsNewer() bool {
	return e.data[27] == 0x10
}

func (e *CommonVideoStream) ToNewer() *NewerVideoStream {
	return &NewerVideoStream{*e}
}

func (e *CommonVideoStream) ToOlder() *OlderVideoStream {
	return &OlderVideoStream{*e}
}

/*
新协议视频流
*/
type NewerVideoStream struct {
	CommonVideoStream
}

func (e *NewerVideoStream) IsAudio() bool {
	return e.data[41] == 2
}

/*
*
获取帧类型 2:音频帧 1:I关键帧 0:P帧
*/
func (e *NewerVideoStream) GetFrameType() uint8 {
	return e.data[41]
}

/*
*
获取帧的序号
*/
func (e *NewerVideoStream) GetFrameSort() uint16 {
	return ToUint16(e.data[37:39])
}

/*
*
获取帧的包总数
*/
func (e *NewerVideoStream) GetFrameBagCount() uint16 {
	return ToUint16(e.data[35:37])
}

/*
*
获取帧内的包序号
*/
func (e *NewerVideoStream) GetFrameBagSort() uint16 {
	return ToUint16(e.data[33:35])
}

/*
*

	获取95包里面的H264裸流
*/
func (e *NewerVideoStream) GetFrameData() []byte {
	return e.data[51 : len(e.data)-5]
}

func (e *NewerVideoStream) GetPassageCode() uint16 {
	return ToUint16(e.data[39:41])
}

func (e *NewerVideoStream) SetPassageCode(v uint16) {
	copy(e.data[39:41], FromUint16(v))
}

func (e *NewerVideoStream) MakeCommand(video, audio uint16) []byte {
	cmd := new(NewerVideoCommand)
	cmd.Load(cmd.Template())
	copy(cmd.data[7:28], e.data[7:28])
	cmd.SetStatusActionCode(0x01)
	cmd.SetTransMode(e.GetTransMode())
	cmd.SetPassageCode(video, audio)
	return cmd.Done()
}

/*
旧协议视频流
*/
type OlderVideoStream struct {
	CommonVideoStream
}

func (e *OlderVideoStream) GetPassageID() byte {
	return e.data[31]
}

func (e *OlderVideoStream) SetPassageID(v byte) {
	e.data[31] = v
}

func (e *OlderVideoStream) MakeCommand(passage uint16) []byte {
	cmd := new(OlderVideoCommand)
	cmd.Load(cmd.Template())
	copy(cmd.data[7:28], e.data[7:28])
	cmd.SetStatusActionCode(0x01)
	cmd.SetTransMode(e.GetTransMode())
	cmd.SetPassageCode(passage)
	return cmd.Done()
}

/*
查询录像
a0-c6
*/
type RecordQuery struct {
	base1246
}

/*
查询类型
0x01 查询当月有录像的日期
0x02 查询当天有录像的时间段
0x03 查询当月有录像的日期[灾备]
0x04 查询当天有录像的时间段[灾备]
*/
func (e *RecordQuery) GetQueryType() byte {
	return e.data[27]
}

func (e *RecordQuery) SetQueryType(v byte) {
	e.data[27] = v
}

// 是否是有录像的日期
func (e *RecordQuery) IsQueryForDate() bool {
	return e.data[27] == 1 || e.data[27] == 3
}

func (e *RecordQuery) Template() []byte {
	data, _ := hex.DecodeString("a00024020002c6010000025a02000188ce04715658e806613aee10011509000000070da1")
	return data
}

/*
获取要查询的年月日
查询日期时，数据包中相应的位置为0
*/
func (e *RecordQuery) GetDate() (year, month, day int) {
	return int(e.data[28]), int(e.data[29]), int(e.data[30])
}

func (e *RecordQuery) SetDate(year, month, day int) {
	e.data[28], e.data[29], e.data[30] = byte(year), byte(month), byte(day)
}

/*
查询录像的结果
*/
type RecordResult struct {
	base1246
}

func (e *RecordResult) GetQueryType() byte {
	return e.data[27]
}

func (e *RecordResult) IsQueryForDate() bool {
	return e.data[27] == 1 || e.data[27] == 3
}

func (e *RecordResult) IsSuccess() bool {
	return e.data[28] == 1
}

/*
获取要查询的年月日
查询日期时，数据包中没有日期的位置
*/
func (e *RecordResult) GetDate() (year, month, day int) {
	if e.IsQueryForDate() {
		return int(e.data[29]), int(e.data[30]), 0
	} else {
		return int(e.data[29]), int(e.data[30]), int(e.data[31])
	}
}

func (e *RecordResult) SetDate(year, month, day int) {
	if e.IsQueryForDate() {
		e.data[29], e.data[30] = byte(year), byte(month)
	} else {
		e.data[29], e.data[30], e.data[31] = byte(year), byte(month), byte(day)
	}
}

/*
(查询日期时)获取按位编码的日期
从低位到高位(从后到前)每一位表示一个日期
*/
func (e *RecordResult) GetDateCode() uint32 {
	return ToUint32(e.data[31:35])
}

/*
(查询时间段时)获取录像的起止时间
*/
func (e *RecordResult) GetTimeRange() (start, end uint32) {
	return ToUint32(e.data[32:36]), ToUint32(e.data[36:40])
}

type RecordTimeSegment struct {
	Hour, Minute, Second byte
	CameraCode           uint16
}

/*
(查询时间段时)获取各时间段摄像头状态
*/
func (e *RecordResult) GetTimeSegments() []RecordTimeSegment {
	res := make([]RecordTimeSegment, 0)
	for offset := 40; offset < len(e.data)-9; offset += 5 {
		res = append(res, RecordTimeSegment{
			Hour:       e.data[offset],
			Minute:     e.data[offset+1],
			Second:     e.data[offset+2],
			CameraCode: ToUint16(e.data[offset+3 : offset+5]),
		})
	}
	return res
}
